#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <stdlib.h>

#define NUM 1024

typedef struct MyFILE_ {
    int fd;
    char buffer[1024];
    int end; //缓冲区的结尾
}MyFILE;

//FILE *fopen(const char *path, const char *mode);
MyFILE* fopen_(const char* pathname, const char* mode)
{
    assert(pathname);
    assert(mode);

    MyFILE* fp = NULL;

    if (strcmp(mode, "r") == 0) {}
    else if (strcmp(mode, "r+") == 0) {}

    else if (strcmp(mode, "w") == 0)
    {
        int fd = open(pathname, O_WRONLY | O_TRUNC | O_CREAT, 0666);
        if (fd >= 0)
        {
            fp = (MyFILE*)malloc(sizeof(MyFILE));
            memset(fp, 0, sizeof(MyFILE));
            fp->fd = fd;
        }
    }

    else if (strcmp(mode, "w+") == 0) {}
    else if (strcmp(mode, "a") == 0) {}
    else if (strcmp(mode, "a+") == 0) {}
    else perror("fopen_");

    return fp;
}

//C标准库中的实现 int fputs(const char *s, FILE *stream);
void fputs_(const char* message, MyFILE* fp)
{
    assert(message);
    assert(fp);

    strcpy(fp->buffer + fp->end, message); //abcde\n\0
    fp->end += strlen(message);

    //debug
   // printf("%s\n", fp->buffer);

    //刷新策略是用户通过执行C标准库中的代码逻辑来完成刷新动作
    //C提供了缓冲区，通过刷新策略，减少了IO的执行次数(不是数据量大小)
    if (fp->fd == 0)
    {
        //标准输入
    }
    else if (fp->fd == 1)
    {
        //标准输出
        if (fp->buffer[fp->end - 1] == '\n')
        {
            //close(1) debug: 模拟文件中的实时内容变化
            //int fprintf(FILE *stream, const char *format, ...);
            //fprintf(stderr, "fflush: %s", fp->buffer); //2

            //ssize_t write(int fd, const void *buf, size_t count);
            write(fp->fd, fp->buffer, fp->end);
            fp->end = 0;
        }
    }
    else if (fp->fd == 2)
    {
        //标准错误
    }
    else
    {
        //其他文件
    }
}


void fflush_(MyFILE* fp)
{
    assert(fp);

    if (fp->end != 0)
    {
        //ssize_t write(int fd, const void *buf, size_t count);
        write(fp->fd, fp->buffer, fp->end);
        //int syncfs(int fd);
        syncfs(fp->fd); 
        fp->end = 0;
    }
}

void fclose_(MyFILE* fp)
{
    assert(fp);
    fflush_(fp);
    close(fp->fd);
    free(fp);
}

int main()
{
    //close(1);// 关闭1 此时log.txt的fd不再是3而是1 刷新策略从满刷新-->行刷新
    MyFILE* fp = fopen_("./log.txt", "w");
    if (fp == NULL)
    {
        printf("open file error");
        return 1;
    }
    //else{
    //    printf("%d\n", fp -> fd);
    //}

    fputs_("one: hello world", fp);

    //debug: 
    //fork();

    fclose_(fp);

    return 0;
}
